home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Utilities / System / FKey / FKeys / tsv4.0.2 / src / TogSndVol4.0.2.c < prev    next >
C/C++ Source or Header  |  1992-07-04  |  9KB  |  292 lines

  1. /* 
  2.  * ToggleSndVol FKEY 4.0.2
  3.  * ©1990-2, by Mike Gleason Jr., NCEMRSoft 
  4.  * This Think C Source code may be distributed freely. 
  5.  * 
  6.  * Think C setup:
  7.  * Make a project and add MacTraps.  Set Project Type to "Code Resource,"
  8.  * and set the TYPE to "FKEY" and the ID number to 7 (or whatever…).
  9.  * I also suggest setting the "Attrs" to "purgeable" only, & the name to
  10.  * ToggleSndVol 4.0.2.  Compile it and merge it with "TSV Installer π.rsrc."
  11.  */
  12.  
  13. #ifndef __SOUND__
  14. #    include <Sound.h>
  15. #endif
  16.  
  17. #define kCancelButtonID         8        /* id number of "Cancel" */
  18. #define kAboutButtonID            9        /* id number of "?" */
  19. #ifndef NULL
  20. #    define NULL                    ((void *) 0)    /* duh */
  21. #endif
  22. #define kSmallButtonSize        15        /* how wide and tall a button is */
  23. #define kButtonMargin            3        /* number of pixels between buttons */
  24. #define kWindowWidth            222        /* dimensions of the window in pixels */
  25. #define kWindowHeight            23
  26. #define kWindowExtend            115        /* Make the window this much longer when */
  27.                                         /* the about button is clicked. */
  28. #define    kWNETrapNum                0x60    /* Trap number of WaitNextEvent() */
  29. #define    kUnImplTrapNum            0x9F    /* Trap number "unimplemented trap" */
  30. #define kMinSleep                30L        /* for WaitNextEvent */
  31.  
  32.                                         /* You can debug the FKEY by making */
  33.                                         /* this an application project, and */
  34.                                         /* the FKEY will run as a tiny app. */
  35.  
  36. #if __option(a4_globals)                /* Is this a code resource project? */
  37. #    define FKEY
  38. #endif
  39.  
  40. /* function prototypes... */
  41. void    DoIt(void);                        /* the main event loop */
  42. Boolean    ModifierDown(void);                /* is the option, shift, or cmd down? */
  43. void    SaveToPRAM(short newvol);        /* write newvol to the control panel PRAM */
  44. void    SetTheVolume(short theVol);        /* sets the speaker's volume */
  45. void    DoAbout(WindowPtr w);
  46.                                         /* extend the window, show info */
  47.  
  48. #ifdef FKEY
  49. #    include <SetUpA4.h>
  50. #endif
  51.  
  52. void DoAbout(WindowPtr w)
  53. {
  54.     Rect r;
  55.      static char text[] =
  56.          "ToggleSndVol FKEY 4.0.2\r©1992 by Mike Gleason, NCEMRSoft.\r\rClicking or typing a number sets the sound volume in the Control Panel to that number.  Hold"
  57.         "ing down the option key will NOT save the result to the PRAM (the change will only last for this boot).  This FKEY is FREE, "
  58.         "but distribution on media greater than 2MB requires my permission.";
  59.  
  60.         /*     All DoAbout() does is stretch the window down when the "?" */
  61.         /*    button is clicked so I can put up my about info. */
  62.         
  63.     if (w->portRect.bottom > kWindowHeight) return;
  64.         /* (The window has already been stretched and is showing the info) */
  65.     
  66.     SetPort(w);
  67.     TextFont(geneva);
  68.     TextSize(9);
  69.     SizeWindow(w, w->portRect.right, w->portRect.bottom + kWindowExtend, TRUE);
  70.     r = w->portRect;
  71.     r.top = kWindowHeight + 3;
  72.     TextBox(text, sizeof (text) - 1, &r, teJustLeft);
  73. }    /* DoAbout */
  74.  
  75.  
  76.  
  77.  
  78. void SaveToPRAM(short newvol)
  79. {
  80.     SysPPtr                sp;
  81.     
  82.     sp = GetSysPPtr();            /* a pointer to the PRAM */
  83.     newvol = (newvol & 0x07) << 8;        
  84.  
  85.     /*     This block compares 3 bits in our volume to 3 in that of the
  86.         sp->volClik field.  We can't just say sp->volClik = newvol
  87.         because other "useful" data is stored in the other 13 bits
  88.         of the field.  essentially, this replaces the old 3 bits
  89.         with our 3 bits. */
  90.  
  91.     sp->volClik = (sp->volClik & 0xf8ff) | newvol;
  92.     (void) WriteParam();    /* now save the changed sp to the PRAM */
  93. }    /* SaveToPRAM */
  94.  
  95.  
  96.  
  97.  
  98. Boolean ModifierDown(void)
  99. {
  100.     KeyMap k;
  101.  
  102.     GetKeys(k);
  103.     return (
  104.             (((char *)k)[7] & 0x05)        /* option or shift */
  105.         ||    (((char *)k)[6] & 0x80)        /* command */
  106.     );
  107. }    /* ModifierDown */
  108.  
  109.  
  110.  
  111.  
  112. void SetTheVolume(short theVol)
  113. {
  114.     /*    If the option key is not down, we'll assume the change is         */
  115.     /*    permanent; if it is down, we won't store the change in the PRAM. */
  116.  
  117.     if (!ModifierDown())
  118.         SaveToPRAM(theVol);
  119.     SetSoundVol(theVol);
  120.     SysBeep(3);    /*    Beep so the user can hear the new volume. */
  121. }    /* SetTheVolume */
  122.  
  123.  
  124.  
  125.  
  126. void DoIt(void)
  127. {
  128.     short            i, sndVol, ch, done = 0;
  129.     long            dummy;
  130.     Rect             itemRect, ScreenBitsBounds, theRect = {0, 0, kWindowHeight, kWindowWidth};
  131.     WindowPtr        theWind;
  132.     ControlHandle    buttons[10], whichControl;
  133.     Str255            title;
  134.     EventRecord        theEvent;
  135.     Boolean            hasWaitNextEvent, haveEvt;
  136.     GrafPtr            savedPort;
  137.     GrafPort        tempPort;
  138.     
  139.     GetPort(&savedPort);        /* We'll need this later. */
  140.     
  141.     /* find screenBits w/o using quickdraw globals */
  142.     OpenPort(&tempPort);
  143.     ScreenBitsBounds = tempPort.portRect;
  144.     ClosePort(&tempPort);
  145.  
  146.     /*    This block of statements creates and centers our window's rectangle. */
  147.     OffsetRect(&theRect, (ScreenBitsBounds.right - theRect.right) / 2, (ScreenBitsBounds.bottom - theRect.bottom) / 3);
  148.  
  149.     /*    OK, we've got the rectangle, now make the window. */
  150.     theWind = NewWindow((Ptr) 0, &theRect, "\p", true, dBoxProc, (WindowPtr) -1, false, 0L);
  151.     if (!theWind) return;
  152.  
  153.     /*    Get ready to draw in our window */
  154.     SetPort(theWind);
  155.     SelectWindow(theWind);
  156.  
  157.     /*    Create the first button's rectangle. */
  158.     theRect.left = theRect.top = 2;
  159.     theRect.bottom = theRect.right = theRect.top + kSmallButtonSize;
  160.     
  161.     /* This loop creates 8 little buttons, numbered 0-7. */
  162.     for (i=0; i<8; i++) {
  163.         NumToString((long) i, title);    /* convert 3 to "3", etc. */
  164.         buttons[i] = NewControl(
  165.             theWind,
  166.             &theRect,
  167.             title,
  168.             true,
  169.             0,
  170.             0,
  171.             0,
  172.             pushButProc,
  173.             i
  174.         );
  175.         if (!buttons[i]) return;
  176.         /* Shift the rectangle to use for the next button. */
  177.         theRect.right += kSmallButtonSize + kButtonMargin;
  178.         theRect.left += kSmallButtonSize + kButtonMargin;
  179.     }
  180.     
  181.     /*    We've already got the rectangle, but it's too narrow.    */
  182.     /*    Add on enough pixels to fit in the word "Cancel."        */
  183.     theRect.right += /* StringWidth("\pCancel") */   41;
  184.     buttons[kCancelButtonID] = NewControl(theWind, &theRect, "\pCancel", 1,0,0,0,0,kCancelButtonID);
  185.     if (!buttons[kCancelButtonID]) return;
  186.     
  187.     /*    Grr... Now we need the old dimensions back for a small button. */
  188.     theRect.right += kSmallButtonSize + kButtonMargin;
  189.     theRect.left = theRect.right - kSmallButtonSize;
  190.     buttons[kAboutButtonID] = NewControl(theWind, &theRect, "\p?", 1,0,0,0,0,kAboutButtonID);
  191.     if (!buttons[kAboutButtonID]) return;
  192.     
  193.     /*     This block gets the current sound volume, so we can put a dot    */
  194.     /*    under the appropriate button in the window to tell the user        */
  195.     /*    what the current speaker volume is.                                */
  196.     GetSoundVol(&sndVol);
  197.     theRect.left = ((**buttons[sndVol]).contrlRect.right-(**buttons[sndVol]).contrlRect.left)/2 - 2 + (**buttons[sndVol]).contrlRect.left;
  198.     theRect.top = (**buttons[sndVol]).contrlRect.bottom+2;
  199.     theRect.right = theRect.left + 4;
  200.     theRect.bottom = theRect.top + 4;
  201.     PaintOval(&theRect);
  202.     
  203.     hasWaitNextEvent = (Boolean) (NGetTrapAddress(kWNETrapNum, ToolTrap) != NGetTrapAddress(kUnImplTrapNum, ToolTrap));
  204.  
  205.     /*    Now everything should be up and running.  What follows is a        */
  206.     /*    short and ugly event loop;  We only care about mouseDown and    */
  207.     /*    keyDown events.                                                    */
  208.  
  209.     while (!done) {
  210.         if (hasWaitNextEvent)
  211.             haveEvt = WaitNextEvent(everyEvent, &theEvent, kMinSleep, NULL);
  212.         else {
  213.             SystemTask();
  214.             haveEvt = GetNextEvent(everyEvent, &theEvent);
  215.         }
  216.         if (haveEvt) {
  217.             SetPort(theWind);
  218.             if (theEvent.what == mouseDown) {
  219.                 GlobalToLocal(&theEvent.where);
  220.                 if (FindControl(theEvent.where, theWind, &whichControl)) {
  221.                     /* see which button it was, and hilite it as needed. */
  222.                     if (TrackControl(whichControl, theEvent.where, 0L)) {
  223.                         ch = (short) (**whichControl).contrlRfCon;
  224.                         goto x;        /* it's a "goto," but it saves bytes. */
  225.                     }
  226.                 }
  227.             } else if (theEvent.what == keyDown || theEvent.what == autoKey) {
  228.                 ch = (short) (theEvent.message & charCodeMask);
  229.                 if (ch >= '0' && ch <= '7')
  230.                     ch -= '0';    /* convert ch to a number */
  231.                 else if (ch == '/' || ch == '?')
  232.                     ch = kAboutButtonID;    /* about */
  233.                 else
  234.                     ch = kCancelButtonID;    /* cancel */
  235.                 whichControl = buttons[ch];
  236.                 HiliteControl(whichControl, 1);    /* psuedoclick the button */
  237.                 Delay(20L, &dummy);
  238.                 HiliteControl(whichControl, 0);
  239. x:
  240.                 done = 1;
  241.                 if (ch < kCancelButtonID && ch >= 0)
  242.                     SetTheVolume(ch);
  243.                 else if (ch == kAboutButtonID) {
  244.                     DoAbout(theWind);
  245.                     HiliteControl(whichControl, 255);    /* dimmed. */
  246.                     done = 0;
  247.                 }
  248.             }
  249.         }
  250.     }
  251.  
  252.     DisposeWindow(theWind);
  253.     SetPort(savedPort);
  254. }    /* DoIt */
  255.  
  256.  
  257.  
  258.  
  259. pascal void main(void) 
  260. {
  261. #ifdef FKEY
  262.     Handle            h;
  263.  
  264.     RememberA0();    /* This and the asm stuff guarantees that this code */
  265.     SetUpA4();        /* resource is locked while it is executing. */
  266.  
  267.     asm {                        ;guarantee that it is locked even
  268.         _RecoverHandle            ;  if locked bit was not set with ResEdit.
  269.         move.l    a0,h            ;save away handle to unlock later.
  270.         _HLock                    ;handle is already in a0.
  271.     }
  272.     InitCursor();
  273.     DoIt();
  274.     HUnlock(h);
  275.     RestoreA4();
  276. #else    /* we're testing with an application. */
  277.     MaxApplZone();
  278.     InitGraf(&thePort);
  279.     InitFonts();
  280.     FlushEvents(everyEvent, 0);
  281.     InitWindows();
  282.     InitMenus();
  283.     TEInit();
  284.     InitDialogs(0L);
  285.     InitCursor();
  286.  
  287.     DoIt();
  288. #endif
  289. }    /* main */
  290.  
  291. /* eof */
  292.